/**
 * 
 */
package br.edu.ufcg.embedded.mysocial;

import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import br.edu.ufcg.embedded.util.FileConsumer;
import br.edu.ufcg.embedded.util.MultiFileGenerator;
import br.embedded.socialapp.business.Usuario;

import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultEdge;

import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.json.JettisonMappedXmlDriver;

/**
 * @author daniel
 *
 */
public class GraphCacheManager
{
	private Hashtable<String, Hashtable<Integer, LinkedHashSet<String>>> hashtable;
	private static Graph<Usuario, DefaultEdge> graph;
	private List<Usuario> jobList;
	private int maxLevels;
	
	private List<GraphCache3> runnableThreads;
	private int threadCount;
	private FileConsumer fileConsumer;
	
	private final String PATH = "/home/daniel/workspace/SocialNetsAppClient/";
	private final String FILE_EXTENSION = ".csv";
	
	private int maxRecords;
	private final long SLEEP_TIME = 100;
	
	public GraphCacheManager(Graph<Usuario, DefaultEdge> g, List<Usuario> jobList, int maxLevels, int threadCount, int maxRecords)
	{
		this.hashtable = new Hashtable<String, Hashtable<Integer, LinkedHashSet<String>>>();
		graph = g;
		this.jobList = jobList;
		this.maxLevels = maxLevels;
		this.maxRecords = maxRecords;
		
		this.threadCount = threadCount;
		this.runnableThreads = new ArrayList<GraphCache3>(threadCount);
		
		this.createThreads();
	}
	
	private void createThreads()
	{
		List<List<Usuario>> lists = createLists();
		
		//int startIndex = 0;
		//int endIndex = 0;
		
		//int offset = list.size() / threadCount;
		//int rest = list.size() % threadCount;
		
		//endIndex = offset + rest;
		
		for (int i = 1; i <= threadCount; i++)
		{
			GraphCache3 graphCache3 = new GraphCache3(maxLevels, lists.get(i-1)); //list.subList(startIndex, endIndex));
			
			graphCache3.setName("Thread" + i);
			graphCache3.setMultiFileGenerator(new MultiFileGenerator(PATH, graphCache3.getName(), FILE_EXTENSION, maxRecords));
			
			runnableThreads.add(graphCache3);
			
			//startIndex = endIndex;
			//endIndex = ((endIndex + offset) <= list.size() -1) ? (endIndex + offset) : list.size();
		}
		
		fileConsumer = new FileConsumer(PATH, FILE_EXTENSION);
	}
	
	public void run()
	{
		for (int i = 0; i < runnableThreads.size(); i++) {
			runnableThreads.get(i).start();
		}
		
		fileConsumer.start();
		
		System.out.println("GraphCacheManager: The Threads are running...");
		
		this.monitor();
	}
	
	private void monitor()
	{
		while (true)
		{
			try {
				Thread.sleep(SLEEP_TIME);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			
			int count = 0;
			
			for (int i = 0; i < runnableThreads.size(); i++)
			{
				if (runnableThreads.get(i).getState() == Thread.State.TERMINATED)
					count++;
				else
					break;
			}
			
			if (count == runnableThreads.size())
			{
				fileConsumer.producerFinished();
				break;
			}
		}
	}
		
	public Set<String> getNeighboursAtLevel(String vertex, int level)
	{
		if (containsNeighboursAtLevel(vertex, level))
			return hashtable.get(vertex).get(level);
		
		return null;
	}
	
	public boolean containsNeighboursAtLevel(String vertex, int level)
	{
		return (hashtable.containsKey(vertex) && hashtable.get(vertex).containsKey(level));
	}
	
	public Set<String> getAllVertex()
	{
		return hashtable.keySet();
	}
	
	public static Graph<Usuario, DefaultEdge> getGraph()
	{
		return graph;
	}
	
	private List<List<Usuario>> createLists()
	{
		//List<Usuario> list = new ArrayList<Usuario>(graph.vertexSet());
		List<List<Usuario>> lists = new ArrayList<List<Usuario>>(threadCount);
		
		for (int i = 0; i < threadCount; i++) {
			lists.add(new ArrayList<Usuario>());
		}
		
		for (int j = 0; j < jobList.size(); j++) {
			lists.get(j % threadCount).add(jobList.get(j));
		}
		
		return lists;
	}
		
/*	private void read()
	{
		try {
			XStream xStream = new XStream(new JettisonMappedXmlDriver());
			Graph<Usuario, DefaultEdge> graph1 = (Graph<Usuario, DefaultEdge>) xStream.fromXML(compressor.decompress(compressedGraph));
			System.out.println(graph1.vertexSet().size() + " - " + graph1.edgeSet().size());
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}*/
}
